package org.scau.studentevaluation.config;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;

/**
 * @ClassName: JsonUtils
 * 主要给feign解码器用的
 * 会在反序列化忽略找不到的字段
 * @Description: TODO
 * @Author: sunslikes
 * @Date: 2020/9/4 23:34
 * @Version: 1.0
 */
@Component
public class JsonUtils {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    public JsonUtils() {
        // 设置以匹配jdk8时间类
        MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        MAPPER.registerModule(new JavaTimeModule());
        // 设置以反序列化时忽略java中不存在的字段
        MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    @PostConstruct
    public static JsonUtils create() {
        return new JsonUtils();
    }

    /**
     * 给泛型对象用的 T<A，B, C...>
     * @param jsonStr
     * @param rawType
     * @param actualType
     * @param <T>
     * @return
     */
    public static <T> T json2GenricObj(String jsonStr, Class rawType, Class... actualType) {
        try {
            JavaType javaType = MAPPER.getTypeFactory().constructParametricType(rawType, actualType);
            return MAPPER.readValue(jsonStr, javaType);

        } catch (JsonParseException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        } catch (IOException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        }
    }

    /**
     * 泛型对象 T<A<B,C..>>
     * @param jsonStr
     * @param tType
     * @param aType
     * @param bTypes
     * @param <T>
     * @return
     */
    public static <T> T json2GenricGenricObj(String jsonStr, Class tType, Class aType, Class... bTypes) {
        try {
            JavaType innerType = MAPPER.getTypeFactory().constructParametricType(aType,  bTypes);
            JavaType javaType = MAPPER.getTypeFactory().constructParametricType(tType, innerType);
            return MAPPER.readValue(jsonStr, javaType);

        } catch (JsonParseException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        } catch (IOException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        }
    }

    public static <T> T json2obj(String jsonStr, JavaType javaType) {
        try {
            return MAPPER.readValue(jsonStr, javaType);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        } catch (IOException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        }
    }



    /**
     * 对象转换成json
     * @param obj
     * @return
     */
    public static String objectToJson(Object obj){
        if(obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static  <T> T jsonToObject(String responseJson, TypeReference<T> valueTypeRef) {
        try {
            return MAPPER.readValue(responseJson, valueTypeRef);
        } catch (IOException e) {
            throw new IllegalArgumentException("Failed to convert json to object", e);
        }
    }

    public static  <T> T json2Object(String strJson, Class<T> cl) throws IOException {
        return MAPPER.readValue(strJson, cl);
    }
}
